﻿#include "framework.h"
#include "Box.h"
#include "Const.h"

// 全局变量
extern BaseGameObject* gBaseGameObjects[GAME_BOARD_GRID_COUNT_V][GAME_BOARD_GRID_COUNT_H];

// 函数声明
void Box_Delete(BaseGameObject*);
BaseGameObject* Box_Move(BaseGameObject*, UINT, MoveResult*);

/**
 * 创建箱子。
 * @param back      背后对象
 * @param drawer    绘图者
 * @param type      类型
 * @param x, y      左上角坐标
 * @return 箱子
 */
BaseGameObject* New_Box(BaseGameObject* back, HDC drawer, GameObjectType type, int x, int y) {
    TCHAR imageFilePath[MAX_PATH] = { 0 };

    // 创建父类对象
    BaseGameObject* baseGameObject = New_BaseGameObject(drawer, type, x, y);

    // 创建本类对象
    Box* box = (Box*)calloc(1, sizeof(Box));

    // 初始化父类数据
    baseGameObject->mChild = box;

    // 初始化父类函数
    baseGameObject->deleteSelf = Box_Delete;
    baseGameObject->move = Box_Move;

    // 初始化本类数据
    box->mBack = back;
    box->mCurrentImage = baseGameObject->mImage;
    _stprintf_s(imageFilePath, MAX_PATH, IMAGE_FILE_PATH, type * 10 + 1);
    box->mImage2 = LoadImage(NULL, imageFilePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    box->mParent = baseGameObject;

    return baseGameObject;
}

/**
 * 删除箱子。
 * @param baseGameObject    基本游戏物体
 */
void Box_Delete(BaseGameObject* baseGameObject) {
    Box* box = (Box*)baseGameObject->mChild;
    
    // 删除本类
    DeleteObject(box->mImage2);
    box->mBack->deleteSelf(box->mBack);
    free(box);

    // 删除父类
    BaseGameObject_Delete(baseGameObject);
}

/**
 * 移动箱子。
 * @param baseGameObject    基本游戏物体
 * @param direction         方向
 * @param moveResult        移动结果
 * @return 被推动的箱子
 */
BaseGameObject* Box_Move(BaseGameObject* baseGameObject, UINT direction, MoveResult* moveResult) {
    Box* box = (Box*)baseGameObject->mChild;                    // 箱子
    BOOL leftFromDest = FALSE;                                  // 是否离开目的地
    int destX = baseGameObject->mX, destY = baseGameObject->mY; // 新位置的坐标

    // 计算新位置
    if (direction == VK_LEFT) {
        destX--;
    } else if (direction == VK_RIGHT) {
        destX++;
    } else if (direction == VK_UP) {
        destY--;
    } else if (direction == VK_DOWN) {
        destY++;
    }

    // 如果旁边是墙或箱子，则直接返回
    if (gBaseGameObjects[destY][destX]->mType == WALL ||
        gBaseGameObjects[destY][destX]->mType == BOX) {
        *moveResult = NO_MOVE;
        return NULL;
    }

    // 设置移动结果
    if (*moveResult < NORMAL_MOVED) {
        *moveResult = NORMAL_MOVED;
    }

    // 判断是否要离开目的地
    if (baseGameObject->mType == BOX && box->mBack->mType == DESTINATION) {
        leftFromDest = TRUE;
        *moveResult = LEFT_FROM_DEST;
        box->mCurrentImage = baseGameObject->mImage;
    }

    // 用背后对象擦除自己
    box->mBack->draw(box->mBack);
    gBaseGameObjects[baseGameObject->mY][baseGameObject->mX] = box->mBack;

    // 计算新位置
    baseGameObject->mX = destX;
    baseGameObject->mY = destY;

    // 设置新的背后对象
    box->mBack = gBaseGameObjects[baseGameObject->mY][baseGameObject->mX];

    // 判断是否到达目的地
    if (baseGameObject->mType == BOX && box->mBack->mType == DESTINATION) {
        if (leftFromDest) {
            *moveResult = NORMAL_MOVED;
        } else {
            *moveResult = ARRIVED_ON_DEST;
        }
        box->mCurrentImage = box->mImage2;
    }

    // 重绘自己
    SelectObject(baseGameObject->mImageDC, box->mCurrentImage);
    BitBlt(baseGameObject->mDrawer, baseGameObject->mX * GRID_SIZE, baseGameObject->mY * GRID_SIZE, 
        GRID_SIZE, GRID_SIZE, baseGameObject->mImageDC, 0, 0, SRCCOPY);

    // 将自己保存到数组中
    gBaseGameObjects[baseGameObject->mY][baseGameObject->mX] = baseGameObject;

    return baseGameObject;
}
